/**
 *   Copyright (c) fanguangping. All rights reserved.
 *   The use and distribution terms for this software are covered by the
 *   Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
 *   which can be found in the file epl-v10.html at the root of this distribution.
 *   By using this software in any fashion, you are agreeing to be bound by
 * 	 the terms of this license.
 *   You must not remove this notice, or any other, from this software.
 **/
package org.jfunny.core.sys;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jfunny.core.JFunny;
import org.jfunny.core.mapping.IMapping;
import org.jfunny.core.mapping.SysMapping;
import org.jfunny.core.meta.Namespace;
import org.jfunny.core.util.FileUtil;
import org.jfunny.core.util.StringUtil;

import clojure.lang.RT;

/**
 * 系统加载器
 * 
 * @author fanguangping
 *
 */
public class SysLoader {
	public static final String PROPERTIES_FILE = "sys.properties";

	private static final String SYS_EVALUATOR_KEY = "SysEvaluator";
	private static final String CORE_NAMESPACE_KEY = "CoreNamespace";
	private static final String CORE_TEMPLATE_KEY = "CoreTemplate";
	private static final String RESULT_SUFFIX_KEY = "ResultSuffix";

	//global settings
	public static final String sysEvaluatorClassName;
	public static final String coreNamespace;
	public static final String coreTemplate;
	public static final String resultSuffix;

	static {
		sysEvaluatorClassName = FileUtil.getConfigValue(PROPERTIES_FILE, SYS_EVALUATOR_KEY);
		coreNamespace = FileUtil.getConfigValue(PROPERTIES_FILE, CORE_NAMESPACE_KEY);
		coreTemplate = FileUtil.getConfigValue(PROPERTIES_FILE, CORE_TEMPLATE_KEY);
		resultSuffix = FileUtil.getConfigValue(PROPERTIES_FILE, RESULT_SUFFIX_KEY);
	}

	public static final String SYS_TEMPLATE_PATH = "sys.tpl";
	public static final String SYS_NAMESPACE = "org.jfunny.sys";

	//global settings
	public static Map<Namespace, List<IMapping>> MAPPINGS = null;
	public static Set<String> FUNCTIONS = null;

	public static ISysEvaluator sysEvaluator = null;

	public static void load() throws Exception {
		MAPPINGS = new HashMap<Namespace, List<IMapping>>();

		//加入系统命名空间
		File sysTemplate = new File(SYS_TEMPLATE_PATH);
		String template = FileUtil.readTxt(SYS_TEMPLATE_PATH);
		Namespace sysNamespace = new Namespace(SYS_NAMESPACE);
		sysNamespace.setFile(sysTemplate);
		sysNamespace.setSource(template);
		sysNamespace.setTemplateSpace(true);
		JFunny.allNamespace.add(sysNamespace);
		JFunny.usedNamespace.add(sysNamespace);

		//加载系统模板
		MAPPINGS.put(sysNamespace, parseTemplate(sysNamespace.getSource()));
		FUNCTIONS = new HashSet<String>();

		Class c = Class.forName(sysEvaluatorClassName);
		sysEvaluator = (ISysEvaluator) c.newInstance();

		//加载核心模板
		loadCoreTemplate();

		RT.init();
	}

	private static void loadCoreTemplate() throws Exception {
		File coreTpl = new File(coreTemplate);
		String core = FileUtil.readTxt(coreTemplate);
		Namespace coreNs = new Namespace(coreNamespace);
		coreNs.setFile(coreTpl);
		coreNs.setSource(core);
		coreNs.setTemplateSpace(true);
		JFunny.allNamespace.add(coreNs);
		JFunny.usedNamespace.add(coreNs);

		//JFunny.parse(coreNs, core);
	}

	public static boolean loaded() {
		return (MAPPINGS != null);
	}

	public static List<IMapping> getSysMappings() {
		Namespace sysNs = Namespace.findNamespace(MAPPINGS.keySet(), SYS_NAMESPACE);
		return MAPPINGS.get(sysNs);
	}

	public static List<IMapping> getAllMappings() {
		List<IMapping> mappings = new ArrayList<IMapping>();
		for (Namespace ns : JFunny.usedNamespace) {
			List<IMapping> nsMapping = SysLoader.MAPPINGS.get(ns);
			if (nsMapping != null) {
				mappings.addAll(nsMapping);
			}
		}

		return mappings;
	}

	public static List<IMapping> getUsedMappings(Namespace namespace) {
		if (namespace == null) {
			return getAllMappings();
		}

		List<IMapping> mappings = new ArrayList<IMapping>();

		List<IMapping> nsMapping = SysLoader.MAPPINGS.get(namespace);
		if (nsMapping != null) {
			mappings.addAll(nsMapping);
		}

		nsMapping = SysLoader.MAPPINGS.get(Namespace.findNamespace(MAPPINGS.keySet(), SYS_NAMESPACE));
		if (nsMapping != null) {
			mappings.addAll(nsMapping);
		}

		nsMapping = SysLoader.MAPPINGS.get(Namespace.findNamespace(MAPPINGS.keySet(), coreNamespace));
		if (nsMapping != null) {
			mappings.addAll(nsMapping);
		}

		for (Namespace ns : namespace.getUsed()) {
			nsMapping = SysLoader.MAPPINGS.get(ns);
			if (nsMapping != null) {
				mappings.addAll(nsMapping);
			}
		}

		return mappings;
	}

	/**
	 * 目前系统模板由 "statement:" 和 "->" 作为分隔符
	 * @return
	 */
	private static List<IMapping> parseTemplate(String template) {
		List<IMapping> statements = new ArrayList<IMapping>();

		String[] srcs = StringUtil.removeComments(template, "$").split("statement:");
		for (String src : srcs) {
			String trimSrc = (src == null) ? null : src.trim();
			if (trimSrc != null && !"".equals(trimSrc)) {
				String[] trimSrcs = trimSrc.split("->");

				String key = trimSrcs[0].trim();
				String value = trimSrcs[1].trim();
				SysMapping mapping = new SysMapping(key, value);

				statements.add(mapping);
			}
		}

		return statements;
	}
}
